#pragma once
#include <iostream>
using namespace std;
#include <unistd.h>
#include <string>
#include <pthread.h>
#include "log.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <string.h>
#include <sys/wait.h>
#include <functional>
#include "protocol.hpp"

namespace Server
{
    class httpServer
    {
        typedef function<bool(const httpRequest &, httpResponse &)> func_t;

    public:
        httpServer(func_t fun, const uint16_t &port) : _callback(fun), listen_sock(-1), _port(port)
        {
        }

        void initServer()
        {
            // 1:打开socket
            listen_sock = socket(AF_INET, SOCK_STREAM, 0);
            if (listen_sock < 0)
            {
                logMessage(4, "socket errno");
                exit(1);
            }
            logMessage(1, "socket success");

            // 2:进行bind
            sockaddr_in local; // 封装结构体数据
            bzero(&local, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;

            int n = bind(listen_sock, (sockaddr *)&local, sizeof(local));
            if (n < 0)
            {
                logMessage(4, "bind errno");
                exit(1);
            }
            logMessage(1, "bind success");

            // 3:开启监听模式
            int ret = listen(listen_sock, 5);
            if (ret < 0)
            {
                logMessage(3, "listen errno");
                exit(2);
            }
            logMessage(1, "listen success");
        }

        void HandlerHttp(int sock)
        {
            // 1:读到完整的http请求:这个时候的数据已经是序列化的
            // 2：反序列化：把关键的数据拆分出来
            // 3：回调方法 _callback(req,resp)：处理的业务逻辑
            // 4:resp序列化：处理完后存放到resp响应中，然后再打包序列化
            // 5：send：最后发回给客户端

            char buffer[1024];
            httpRequest req;
            httpResponse resp;
            ssize_t n = recv(sock, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                req.inbuffer = buffer;

                req.parse();

                _callback(req, resp); // 业务逻辑处理
                send(sock, resp.outbuffer.c_str(), resp.outbuffer.size(), 0);
            }
        }

        void start()
        {
            // 4：开始accept
            while (1)
            {
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);

                int sock = accept(listen_sock, (sockaddr *)&peer, &len);
                if (sock < 0)
                {
                    logMessage(2, "accept fail");
                    continue;
                }
                logMessage(1, "accept success");
                cout << "sock: " << sock << endl;

                // 5：采用多进程的版本
                pid_t id = fork();
                if (id == 0)
                {
                    // 子进程
                    close(listen_sock);
                    if (fork() > 0)
                        exit(0); // 退出子进程
                    // 下面是孙子进程

                    // todo
                    HandlerHttp(sock);

                    close(sock);
                    exit(0);
                }

                close(sock);
                waitpid(id, nullptr, 0);
            }
        }

        ~httpServer()
        {
        }

    private:
        func_t _callback;

        int listen_sock;
        uint16_t _port;
    };
}